#include "ecbm_core.h"  //加载库函数的头文件。

#include "cc9d.h"  
#include "byte_queue.h"  

void receive_all_buf();
void sendPkg();



volatile uint8 flag_cc9d_receive = 0;
volatile uint8 flag_10ms = 0;


void main(void){        //main函数，必须的。
		uint16 tick;
    system_init();      //系统初始化函数，也是必须的。
		uart_init();
		exti_init();
		timer_init();
		P2M0 = 0;
		P2M1 = 0;
		P20 = 0;
		EA = 1;
		P20 = !P20;
		timer_start(0);
    while(1){
			tick++;
			if(tick>=500){
				tick = 0;
				sendPkg();
				P20 = !P20;
			}
			if(flag_cc9d_receive != 0){	
				flag_cc9d_receive = 0;			
				receive_all_buf();
			}
			while(flag_10ms==0);
			flag_10ms--;
    }
}


//测试数据，本机会每隔一定时间发送此数据到特定节点，并将此数据自增
uint16 test_num = 0;
//发送一个包的函数，这个程序会将数据发往0xeff1节点，
void sendPkg(){
	cc9d_startSend(0x20,0x22,0xeff1);
	cc9d_sendData('1');
	cc9d_sendData('2');
	cc9d_sendData('3');
	cc9d_sendData('4');
	//Big endding
	cc9d_sendData((uint8)(test_num>>8));
	cc9d_sendData((uint8)test_num);
	cc9d_finishSend();
	test_num++;
}


//创建一个循环队列，用来保存发送序列
#define QUEUE_SIZE 128
byte xdata send_queue_buf[QUEUE_SIZE];
sByteQueue send_queue = {
	0,0,QUEUE_SIZE-1,send_queue_buf
};
uint8 is_sending = 0;//串口正在工作的标记

//发送序列函数，如果串口正在工作就将数据存入缓存。否则将数据发往
uint8 _cc9d_sendByte(uint8 b){
	EA = 0;
	if(is_sending == 0){
    UART2_SET_REG_S2BUF(b);		
		is_sending = 1;
	}else{
		ByteQueue_enqueue(&send_queue,b);
	}
	EA = 1;
	return 0;
}
//串口发送完成中断，从循环队列中取出下一个数进行发送，如果没有后续数要发送，则停止发送
void uart2_send_callback(void){
	int16 b = ByteQueue_dequeue(&send_queue);
	if(b!=-1){
    UART2_SET_REG_S2BUF(b);		
	}
	else	{
		is_sending = 0;
	}
}



//创建一个循环队列，用来保存接收到的数据
byte xdata recv_queue_buf[QUEUE_SIZE];
sByteQueue recv_queue = {
	0,0,QUEUE_SIZE-1,recv_queue_buf
};

//从接收到的内容中取出所有包。
void receive_all_buf(){	
	while(1){
		int16 b = ByteQueue_dequeue(&recv_queue);
		if(b!=-1){
			cc9d_recvbyte(b);
		}
		else	{
			break;
		}
	}
}

//串口接收完成中断，会将接收到的数据保存到队列中，如果遇到0x9d也就是包结束标记，则说明可能收到了一个包
void uart2_receive_callback(void){
	uint8 b = S2BUF;
	ByteQueue_enqueue(&recv_queue,S2BUF);
	if(b == 0x9d){
		flag_cc9d_receive ++;
	}
}

//收到包回调函数，CC9D收到完整的包后会调用这个函数。
//可以尝试发送这样的数据
	//EFF2.48: 30 33
	//EFF2.48: 9d 9e

uint8 _cc9d_receivePkg(byte xdata* buf, uint8 recv_len){
	sCc9dPkg xdata* pkg = (sCc9dPkg xdata*)buf;	
	P25=!P25;
	if(pkg->remote_addr == 0xeff1){
		P26=!P26;
	}
	if(	(pkg->to_port == 0x30)
		&&(recv_len = 4+2)){
	//Big endding
		test_num = *((uint16 xdata*)&(pkg->datas[0]));
		P27=!P27;
	}
	return 0;
}
//下载串口收到数据后复位的中断，用于串口下载程序复位。
void exti4_it_callback(void){
	IAP_CONTR = 0x60;
}


void timer0_it_callback(void){
	flag_10ms++;
}
